Using NodesUsing the Game Effect SystemOn this pageUsing the Game Effect System 1. Introduction In game development, effects are crucial elements that enhance the visual experience. They can enrich the game's atmosphere, highlight key events, and provide instant visual feedback. This tutorial will introduce how to use the Effekseer effect system in the Dora SSR engine, as well as how to utilize the engine's built-in Particle system. 2. What is Effekseer? Effekseer is a free, open-source effect editor that supports multiple platforms including Windows, macOS, and Linux. It allows artists and developers to create a variety of particle effects, such as explosions, flames, beams, and more. Effekseer supports multiple rendering modes and advanced features, such as: Particle Emission and Control: Supports emitting particles from various shapes such as points, lines, and surfaces, with fine control over the particle lifecycle. Rendering Features: Supports blending modes, texture mapping, lighting, and shadows. Multi-Platform Support: Can export effects to various game engines and platforms, including Dora SSR. 3. Using Effekseer The Dora SSR engine has integrated the Effekseer effect system, allowing developers to directly load and play effect files generated by the Effekseer editor (typically with .efk or .efkefc extensions) in their games. 3.1 Using the EffekNode Class In Dora SSR, the EffekNode class can be used to manage the playback of Effekseer effects, acting as a scene node to manage properties like geometric position, rotation, and scale of the effects. Here are the main methods and usages of the EffekNode class: Creating an EffekNode Object LuaTealTypeScriptYueScriptlocal EffekNode <const> = require("EffekNode")local effekNode = EffekNode()local EffekNode <const> = require("EffekNode")local effekNode = EffekNode()import { EffekNode } from "Dora";const effekNode = EffekNode();_ENV = DoraeffekNode = EffekNode! Playing Effects LuaTealTypeScriptYueScriptlocal handle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200), 0)local handle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200), 0)const handle = effekNode.play("Particle/effek/Laser01.efk", Vec2(100, 200), 0);handle = effekNode\play "Particle/effek/Laser01.efk", Vec2(100, 200), 0 The play method accepts the following parameters: filename: The path to the effect file. pos (optional): The two-dimensional coordinates to play the effect, defaulting to (0, 0). z (optional): The Z-axis coordinate to play the effect, defaulting to 0. Stopping Effects LuaTealTypeScriptYueScripteffekNode:stop(handle)effekNode:stop(handle)effekNode.stop(handle);effekNode\stop handle handle: The effect handle returned by the play method. Listening for Effect End Events LuaTealTypeScriptYueScripteffekNode:onEffekEnd(function(handle) print("Effect ended, handle: " .. handle)end)effekNode:onEffekEnd(handle => { print("Effect ended, handle: " .. handle)})effekNode.onEffekEnd(handle => { print("Effect ended, handle: " + handle);});effekNode\onEffekEnd (handle) -> print "Effect ended, handle: #{handle}" 3.2 Practical Example: Playing a Laser Effect Here is a complete example demonstrating how to play a laser effect named Laser01.efk in Dora SSR, along with callback handling when the effect ends. LuaTealTypeScriptYueScript-- Import necessary moduleslocal EffekNode <const> = require("EffekNode")local Vec2 <const> = require("Vec2")-- Create an EffekNode objectlocal effekNode = EffekNode()-- Set the overall 3D rotation angle of the effect nodeeffekNode.angleY = -90-- Play the laser effect at coordinates (100, 200)local laserHandle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200))-- Register effect end callbackeffekNode:onEffekEnd(function(handle) if handle == laserHandle then print("Laser effect ended") endend)-- Import necessary moduleslocal EffekNode <const> = require("EffekNode")local Vec2 <const> = require("Vec2")-- Create an EffekNode objectlocal effekNode = EffekNode()-- Set the overall 3D rotation angle of the effect nodeeffekNode.angleY = -90-- Play the laser effect at coordinates (100, 200)local laserHandle = effekNode:play("Particle/effek/Laser01.efk", Vec2(100, 200))-- Register effect end callbackeffekNode:onEffekEnd(function(handle: integer) if handle == laserHandle then print("Laser effect ended") endend)// Import necessary modulesimport { EffekNode } from "Dora";// Create an EffekNode objectconst effekNode = EffekNode();// Set the overall 3D rotation angle of the effect nodeeffekNode.angleY = -90;// Play the laser effect at coordinates (100, 200)const laserHandle = effekNode.play("Particle/effek/Laser01.efk", Vec2(100, 200));// Register effect end callbackeffekNode.onEffekEnd(handle => { if (handle === laserHandle) { print("Laser effect ended"); }});-- Import necessary modules_ENV = Dora-- Create an EffekNode objecteffekNode = EffekNode!-- Set the overall 3D rotation angle of the effect nodeeffekNode.angleY = -90-- Play the laser effect at coordinates (100, 200)laserHandle = effekNode\play "Particle/effek/Laser01.efk", Vec2(100, 200)-- Register effect end callbackeffekNode\onEffekEnd (handle) -> if handle == laserHandle print "Laser effect ended" 3.3 Controlling the Playback and Stopping of Effects Sometimes, we need to control the playback and stopping of effects based on game logic. For example, playing an effect when a player releases a skill and stopping the effect when the skill is interrupted. LuaTealTypeScriptYueScript-- Assume the skill is interrupted and we need to stop the effecteffekNode:stop(laserHandle)-- Assume the skill is interrupted and we need to stop the effecteffekNode:stop(laserHandle)// Assume the skill is interrupted and we need to stop the effecteffekNode.stop(laserHandle);-- Assume the skill is interrupted and we need to stop the effecteffekNode\stop laserHandle 3.4 Managing Multiple Effects If multiple effects need to be played simultaneously, each effect's handle can be saved separately, and distinctions can be made in the callback. LuaTealTypeScriptYueScript-- Play multiple effectslocal handle1 = effekNode:play("Explosion.efk", Vec2(150, 250))local handle2 = effekNode:play("Sparkle.efk", Vec2(200, 300))-- Callback handlingeffekNode:onEffekEnd(function(handle) if handle == handle1 then print("Explosion effect ended") elseif handle == handle2 then print("Sparkle effect ended") endend)-- Play multiple effectslocal handle1 = effekNode:play("Explosion.efk", Vec2(150, 250))local handle2 = effekNode:play("Sparkle.efk", Vec2(200, 300))-- Callback handlingeffekNode:onEffekEnd(function(handle: integer) if handle == handle1 then print("Explosion effect ended") elseif handle == handle2 then print("Sparkle effect ended") endend)// Play multiple effectsconst handle1 = effekNode.play("Explosion.efk", Vec2(150, 250));const handle2 = effekNode.play("Sparkle.efk", Vec2(200, 300));// Callback handlingeffekNode.onEffekEnd(handle => { if (handle === handle1) { print("Explosion effect ended"); } else if (handle === handle2) { print("Sparkle effect ended"); }});-- Play multiple effectshandle1 = effekNode\play "Explosion.efk", Vec2 150, 250handle2 = effekNode\play "Sparkle.efk", Vec2 200, 300-- Callback handlingeffekNode\onEffekEnd (handle) -> if handle == handle1 print "Explosion effect ended" elseif handle == handle2 print "Sparkle effect ended" 4. Using the Particle Class Before the integration of Effekseer, Dora SSR provided the Particle class for handling 2D particle effects. NoteHowever, the Particle system has limited functionality, mainly relying on the CPU for calculations, resulting in inferior performance and effects compared to Effekseer. Therefore, unless you only wish to create relatively simple particle effects, the use of the Particle class is not recommended. 4.1 Using the Particle Class Creating a Particle Object LuaTealTypeScriptYueScriptlocal Particle <const> = require("Particle")local particle = Particle("effect.par")local Particle <const> = require("Particle")local particle = Particle("effect.par")import { Particle } from "Dora";const particle = Particle("effect.par");_ENV = Doraparticle = Particle "effect.par" The Particle constructor takes one parameter: filename: The path to the particle system definition file. Starting and Stopping Particle Emission LuaTealTypeScriptYueScriptparticle:start() -- Start emitting particlesparticle:stop() -- Stop emitting particlesparticle:start() -- Start emitting particlesparticle:stop() -- Stop emitting particlesparticle.start(); // Start emitting particlesparticle.stop(); // Stop emitting particlesparticle\start! -- Start emitting particlesparticle\stop! -- Stop emitting particles Listening for Particle System End Events LuaTealTypeScriptYueScriptparticle:onFinished(function() print("Particle system ended")end)particle:onFinished(() => { print("Particle system ended")})particle.onFinished(() => { print("Particle system ended");});particle\onFinished () -> print "Particle system ended" 4.2 Usage Example LuaTealTypeScriptYueScript-- Import the Particle classlocal Particle <const> = require("Particle")-- Create a particle system objectlocal particle = Particle("effect.par")-- Register the particle system end callbackparticle:onFinished(function() print("Particle system ended")end)-- Start emitting particlesparticle:start()-- Import the Particle classlocal Particle <const> = require("Particle")-- Create a particle system objectlocal particle = Particle("effect.par")-- Register the particle system end callbackparticle:onFinished(function() print("Particle system ended")end)-- Start emitting particlesparticle:start()// Import the Particle classimport { Particle } from "Dora";// Create a particle system objectconst particle = Particle("effect.par");// Register the particle system end callbackparticle.onFinished(() => { print("Particle system ended");});// Start emitting particlesparticle.start();-- Import the Particle class_ENV = Dora-- Create a particle system objectparticle = Particle "effect.par"-- Register the particle system end callbackparticle\onFinished () -> print "Particle system ended"-- Start emitting particlesparticle\start! 4.3 Customizing Particle Effects Due to the limited functionality of the Particle class, if you need to use it, you might need to modify the engine's particle system editor example (named "Particle"), which is built on the ImGui framework, to create your own particle editor to meet artistic production needs. The .par files used in Dora SSR's particle system are essentially XML formatted text files, and you can refer to the editor code for how to generate and export them. 5. Conclusion This article introduced how to use the Effekseer effect system in the Dora SSR engine. With the EffekNode class, developers can easily load and control various complex effects in their games. We also mentioned the legacy Particle class. Effekseer provides powerful support for the creation and management of game effects, and it is generally recommended to use Effekseer for new projects to handle effects. We hope this tutorial helps you quickly get started with the effect system in Dora SSR and create stunning game effects.